[CCode (cheader_filename="tox/tox.h", cprefix="Tox", lower_case_cprefix="tox_")]
namespace ToxCore {
    namespace Version {
        /**
         * The major version number. Incremented when the API or ABI changes in an
         * incompatible way.
         */
        public const uint32 MAJOR;

        /**
         * The minor version number. Incremented when functionality is added without
         * breaking the API or ABI. Set to 0 when the major version number is
         * incremented.
         */
        public const uint32 MINOR;

        /**
         * The patch or revision number. Incremented when bugfixes are applied without
         * changing any functionality or API or ABI.
         */
        public const uint32 PATCH;

        /**
         * A macro to check at preprocessing time whether the client code is compatible
         * with the installed version of Tox.
         */
        [CCode (cname="TOX_VERSION_IS_API_COMPATIBLE")]
        public static bool is_api_compatible (uint32 major, uint32 minor, uint32 patch);

        /**
        * A macro to make compilation fail if the client code is not compatible with
        * the installed version of Tox.
        */
        [CCode (cname="TOX_VERSION_REQUIRE")]
        public static char require_version (uint32 major, uint32 minor, uint32 patch);

        /**
        * Return the major version number of the library. Can be used to display the
        * Tox library version or to check whether the client is compatible with the
        * dynamically linked version of Tox.
        */
        [CCode (cname="tox_version_major")]
        public static uint32 lib_major ();

        /**
         * Return the minor version number of the library.
         */
        [CCode (cname="tox_version_minor")]
        public static uint32 lib_minor ();

        /**
         * Return the patch number of the library.
         */
        [CCode (cname="tox_version_patch")]
        public static uint32 lib_patch ();

        /**
         * Return whether the compiled library version is compatible with the passed
         * version numbers.
         */
        [CCode (cname="tox_version_is_compatible")]
        public static bool is_compatible (uint32 major, uint32 minor, uint32 patch);

        /**
         * A convenience macro to call tox_version_is_compatible with the currently
         * compiling API version.
         */
        [CCode (cname="TOX_VERSION_IS_ABI_COMPATIBLE")]
        public static bool is_abi_compatible ();
    }

    /**
     * The size of a Tox Public Key in bytes.
     */
    [CCode (cname="TOX_PUBLIC_KEY_SIZE")]
    public const int PUBLIC_KEY_SIZE;

    /**
     * The size of a Tox Secret Key in bytes.
     */
    [CCode (cname="TOX_SECRET_KEY_SIZE")]
    public const int SECRET_KEY_SIZE;

    /**
     * The size of a Tox address in bytes. Tox addresses are in the format
     * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
     *
     * The checksum is computed over the Public Key and the nospam value. The first
     * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
     * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
     */
    [CCode (cname="TOX_ADDRESS_SIZE")]
    public const int ADDRESS_SIZE;

    /**
     * Maximum length of a nickname in bytes.
     */
    [CCode (cname="TOX_MAX_NAME_LENGTH")]
    public const int MAX_NAME_LENGTH;

    /**
     * Maximum length of a status message in bytes.
     */
    [CCode (cname="TOX_MAX_STATUS_MESSAGE_LENGTH")]
    public const int MAX_STATUS_MESSAGE_LENGTH;

    /**
     * Maximum length of a friend request message in bytes.
     */
    [CCode (cname="TOX_MAX_FRIEND_REQUEST_LENGTH")]
    public const int MAX_FRIEND_REQUEST_LENGTH;

    /**
     * Maximum length of a single message after which it should be split.
     */
    [CCode (cname="TOX_MAX_MESSAGE_LENGTH")]
    public const int MAX_MESSAGE_LENGTH;

    /**
     * Maximum size of custom packets. TODO: should be LENGTH?
     */
    [CCode (cname="TOX_MAX_CUSTOM_PACKET_SIZE")]
    public const int MAX_CUSTOM_PACKET_SIZE;

    /**
     * The number of bytes in a hash generated by tox_hash.
     */
    [CCode (cname="TOX_HASH_LENGTH")]
    public const int HASH_LENGTH;

    /**
     * The number of bytes in a file id.
     */
    [CCode (cname="TOX_FILE_ID_LENGTH")]
    public const int FILE_ID_LENGTH;

    /**
     * Maximum file name length for file transfers.
     */
    [CCode (cname="TOX_MAX_FILENAME_LENGTH")]
    public const int MAX_FILENAME_LENGTH;

    /**
     * Represents the possible statuses a client can have.
     */
    [CCode (cname="TOX_USER_STATUS", cprefix="TOX_USER_STATUS_", has_type_id=false)]
    public enum UserStatus {
        /**
        * User is online and available.
        */
        NONE,

        /**
        * User is away. Clients can set this e.g. after a user defined
        * inactivity time.
        */
        AWAY,

        /**
        * User is busy. Signals to other clients that this client does not
        * currently wish to communicate.
        */
        BUSY
    }

    /**
     * Represents message types for tox_friend_send_message and group chat
     * messages.
     */
    [CCode (cname="TOX_MESSAGE_TYPE", cprefix="TOX_MESSAGE_TYPE_", has_type_id=false)]
    public enum MessageType {
        /**
        * Normal text message. Similar to PRIVMSG on IRC.
        */
        NORMAL,

        /**
        * A message describing an user action. This is similar to /me (CTCP ACTION)
        * on IRC.
        */
        ACTION
    }

    /**
     * Protocols that can be used to connect to the network or friends.
     */
    [CCode (cname="TOX_CONNECTION", cprefix="TOX_CONNECTION_", has_type_id=false)]
    public enum ConnectionStatus {
        /**
         * There is no connection. This instance, or the friend the state change is
         * about, is now offline.
         */
        NONE,

        /**
         * A TCP connection has been established. For the own instance, this means it
         * is connected through a TCP relay, only. For a friend, this means that the
         * connection to that particular friend goes through a TCP relay.
         */
        TCP,

        /**
         * A UDP connection has been established. For the own instance, this means it
         * is able to send UDP packets to DHT nodes, but may still be connected to
         * a TCP relay. For a friend, this means that the connection to that
         * particular friend was built using direct UDP packets.
         */
        UDP
    }

    [CCode (cname="enum TOX_FILE_KIND", cprefix="TOX_FILE_KIND_", has_type_id=false)]
    public enum FileKind {
        /**
         * Arbitrary file data. Clients can choose to handle it based on the file name
         * or magic or any other way they choose.
         */
        DATA,

        /**
         * Avatar file_id. This consists of tox_hash(image).
         * Avatar data. This consists of the image data.
         *
         * Avatars can be sent at any time the client wishes. Generally, a client will
         * send the avatar to a friend when that friend comes online, and to all
         * friends when the avatar changed. A client can save some traffic by
         * remembering which friend received the updated avatar already and only send
         * it if the friend has an out of date avatar.
         *
         * Clients who receive avatar send requests can reject it (by sending
         * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by
         * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes
         * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare
         * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar
         * transfer if it matches.
         *
         * When file_size is set to 0 in the transfer request it means that the client
         * has no avatar.
         */
        AVATAR
    }

    [CCode (cname="TOX_FILE_CONTROL", cprefix="TOX_FILE_CONTROL_", has_type_id=false)]
    public enum FileControl {
        /**
        * Sent by the receiving side to accept a file send request. Also sent after a
        * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving.
        */
        RESUME,

        /**
        * Sent by clients to pause the file transfer. The initial state of a file
        * transfer is always paused on the receiving side and running on the sending
        * side. If both the sending and receiving side pause the transfer, then both
        * need to send TOX_FILE_CONTROL_RESUME for the transfer to resume.
        */
        PAUSE,

        /**
        * Sent by the receiving side to reject a file send request before any other
        * commands are sent. Also sent by either side to terminate a file transfer.
        */
        CANCEL,
    }

    /**
    * Type of proxy used to connect to TCP relays.
    */
    [CCode (cname="TOX_PROXY_TYPE", cprefix="TOX_PROXY_TYPE_", has_type_id=false)]
    public enum ProxyType {
        /**
        * Don't use a proxy.
        */
        NONE,

        /**
        * HTTP proxy using CONNECT.
        */
        HTTP,

        /**
        * SOCKS proxy for simple socket pipes.
        */
        SOCKS5
    }

    /**
     * Type of savedata to create the Tox instance from.
     */
    [CCode (cname="TOX_SAVEDATA_TYPE", cprefix="TOX_SAVEDATA_TYPE_", has_type_id=false)]
    public enum SaveDataType {
        /**
        * No savedata.
        */
        NONE,

        /**
        * Savedata is one that was obtained from tox_get_savedata
        */
        TOX_SAVE,

        /**
        * Savedata is a secret key of length TOX_SECRET_KEY_SIZE
        */
        SECRET_KEY
    }
    
    [CCode (cname="TOX_CHAT_CHANGE", cprefix="TOX_CHAT_CHANGE_", has_type_id=false)]
    public enum ChatChange {
        PEER_ADD,
        PEER_DEL,
        PEER_NAME
    }

    [CCode (cname="TOX_ERR_NEW", cprefix = "TOX_ERR_NEW_")]
    public enum ERR_NEW {
        /**
         * The function returned successfully.
         */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The function was unable to allocate enough memory to store the internal
         * structures for the Tox object.
         */
        MALLOC,

        /**
         * The function was unable to bind to a port. This may mean that all ports
         * have already been bound, e.g. by other Tox instances, or it may mean
         * a permission error. You may be able to gather more information from errno.
         */
        PORT_ALLOC,

        /**
         * proxy_type was invalid.
         */
        PROXY_BAD_TYPE,

        /**
         * proxy_type was valid but the proxy_host passed had an invalid format
         * or was NULL.
         */
        PROXY_BAD_HOST,

        /**
         * proxy_type was valid, but the proxy_port was invalid.
         */
        PROXY_BAD_PORT,

        /**
         * The proxy address passed could not be resolved.
         */
        PROXY_NOT_FOUND,

        /**
         * The byte array to be loaded contained an encrypted save.
         */
        LOAD_ENCRYPTED,

        /**
         * The data format was invalid. This can happen when loading data that was
         * saved by an older version of Tox, or when the data has been corrupted.
         * When loading from badly formatted data, some data may have been loaded,
         * and the rest is discarded. Passing an invalid length parameter also
         * causes this error.
         */
        LOAD_BAD_FORMAT,
    }

    [CCode (cname="TOX_ERR_OPTIONS_NEW", cprefix="TOX_ERR_OPTIONS_NEW_")]
    public enum ERR_OPTIONS_NEW {
        /**
        * The function returned successfully.
        */
        OK,
        /**
         * The function failed to allocate enough memory for the options struct.
         */
        MALLOC,
    }

    [CCode (cname="TOX_ERR_BOOTSTRAP", cprefix="TOX_ERR_BOOTSTRAP_")]
    public enum ERR_BOOTSTRAP {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The address could not be resolved to an IP address, or the IP address
         * passed was invalid.
         */
        BAD_HOST,

        /**
         * The port passed was invalid. The valid port range is (1, 65535).
         */
        BAD_PORT
    }

    /**
     * Common error codes for all functions that set a piece of user-visible
     * client information.
     */
    [CCode (cname="TOX_ERR_SET_INFO", cprefix="TOX_ERR_SET_INFO_")]
    public enum ERR_SET_INFO {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * Information length exceeded maximum permissible size.
         */
        TOO_LONG
    }

    [CCode (cname="TOX_ERR_FRIEND_ADD", cprefix="TOX_ERR_FRIEND_ADD_")]
    public enum ERR_FRIEND_ADD {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The length of the friend request message exceeded
         * TOX_MAX_FRIEND_REQUEST_LENGTH.
         */
        TOO_LONG,

        /**
         * The friend request message was empty. This, and the TOO_LONG code will
         * never be returned from tox_friend_add_norequest.
         */
        NO_MESSAGE,

        /**
         * The friend address belongs to the sending client.
         */
        OWN_KEY,

        /**
         * A friend request has already been sent, or the address belongs to a friend
         * that is already on the friend list.
         */
        ALREADY_SENT,

        /**
         * The friend address checksum failed.
         */
        BAD_CHECKSUM,

        /**
         * The friend was already there, but the nospam value was different.
         */
        SET_NEW_NOSPAM,

        /**
         * A memory allocation failed when trying to increase the friend list size.
         */
        MALLOC
    }

    [CCode (cname="TOX_ERR_FRIEND_DELETE", cprefix="TOX_ERR_FRIEND_DELETE_")]
    public enum ERR_FRIEND_DELETE {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * There was no friend with the given friend number. No friends were deleted.
         */
        FRIEND_NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_BY_PUBLIC_KEY", cprefix="TOX_ERR_FRIEND_BY_PUBLIC_KEY_")]
    public enum ERR_FRIEND_BY_PUBLIC_KEY {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * No friend with the given Public Key exists on the friend list.
         */
        NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_GET_PUBLIC_KEY", cprefix="TOX_ERR_FRIEND_GET_PUBLIC_KEY_")]
    public enum ERR_FRIEND_GET_PUBLIC_KEY {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * No friend with the given number exists on the friend list.
         */
        FRIEND_NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_GET_LAST_ONLINE", cprefix="TOX_ERR_FRIEND_GET_LAST_ONLINE_")]
    public enum ERR_FRIEND_GET_LAST_ONLINE {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * No friend with the given number exists on the friend list.
         */
        FRIEND_NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_QUERY", cprefix="TOX_ERR_FRIEND_QUERY_")]
    public enum ERR_FRIEND_QUERY {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The pointer parameter for storing the query result (name, message) was
         * NULL. Unlike the `_self_` variants of these functions, which have no effect
         * when a parameter is NULL, these functions return an error in that case.
         */
        NULL,

        /**
         * The friend_number did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,
    }

    [CCode (cname="TOX_ERR_SET_TYPING", cprefix="TOX_ERR_SET_TYPING_")]
    public enum ERR_SET_TYPING {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The friend number did not designate a valid friend.
         */
        FRIEND_NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_SEND_MESSAGE", cprefix="TOX_ERR_FRIEND_SEND_MESSAGE_")]
    public enum ERR_FRIEND_SEND_MESSAGE {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The friend number did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * An allocation error occurred while increasing the send queue size.
         */
        SENDQ,

        /**
         * Message length exceeded TOX_MAX_MESSAGE_LENGTH.
         */
        TOO_LONG,

        /**
         * Attempted to send a zero-length message.
         */
        EMPTY
    }

    [CCode (cname="TOX_ERR_FILE_CONTROL", cprefix="TOX_ERR_FILE_CONTROL_")]
    public enum ERR_FILE_CONTROL {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The friend_number passed did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * No file transfer with the given file number was found for the given friend.
         */
        NOT_FOUND,

        /**
         * A RESUME control was sent, but the file transfer is running normally.
         */
        NOT_PAUSED,

        /**
         * A RESUME control was sent, but the file transfer was paused by the other
         * party. Only the party that paused the transfer can resume it.
         */
        DENIED,

        /**
         * A PAUSE control was sent, but the file transfer was already paused.
         */
        ALREADY_PAUSED,

        /**
         * Packet queue is full.
         */
        SENDQ
    }

    [CCode (cname="TOX_ERR_FILE_SEEK", cprefix="TOX_ERR_FILE_SEEK_")]
    public enum ERR_FILE_SEEK {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The friend_number passed did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * No file transfer with the given file number was found for the given friend.
         */
        NOT_FOUND,

        /**
         * File was not in a state where it could be seeked.
         */
        DENIED,

        /**
         * Seek position was invalid
         */
        INVALID_POSITION,

        /**
         * Packet queue is full.
         */
        SENDQ
    }

    [CCode (cname="TOX_ERR_FILE_GET", cprefix="TOX_ERR_FILE_GET_")]
    public enum ERR_FILE_GET {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The friend_number passed did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * No file transfer with the given file number was found for the given friend.
         */
        NOT_FOUND
    }

    [CCode (cname="TOX_ERR_FILE_SEND", cprefix="TOX_ERR_FILE_SEND_")]
    public enum ERR_FILE_SEND {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The friend_number passed did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.
         */
        NAME_TOO_LONG,

        /**
         * Too many ongoing transfers. The maximum number of concurrent file transfers
         * is 256 per friend per direction (sending and receiving).
         */
        TOO_MANY
    }

    [CCode (cname="TOX_ERR_FILE_SEND_CHUNK", cprefix="TOX_ERR_FILE_SEND_CHUNK_")]
    public enum ERR_FILE_SEND_CHUNK {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The length parameter was non-zero, but data was NULL.
         */
        NULL,

        /**
         * The friend_number passed did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * No file transfer with the given file number was found for the given friend.
         */
        NOT_FOUND,


        /**
         * File transfer was found but isn't in a transferring state: (paused, done,
         * broken, etc...) (happens only when not called from the request chunk callback).
         */
        NOT_TRANSFERRING,

        /**
         * Attempted to send more or less data than requested. The requested data size is
         * adjusted according to maximum transmission unit and the expected end of
         * the file. Trying to send less or more than requested will return this error.
         */
        INVALID_LENGTH,

        /**
         * Packet queue is full.
         */
        SENDQ,

        /**
         * Position parameter was wrong.
         */
        WRONG_POSITION
    }

    [CCode (cname="TOX_ERR_GET_PORT", cprefix="TOX_ERR_GET_PORT_")]
    public enum ERR_GET_PORT {
        /**
        * The function returned successfully.
        */
        OK,

        /**
         * The instance was not bound to any port.
         */
        NOT_BOUND
    }

    [CCode (cname="TOX_ERR_FRIEND_CUSTOM_PACKET", cprefix="TOX_ERR_FRIEND_CUSTOM_PACKET_")]
    public enum ERR_FRIEND_CUSTOM_PACKET {
        /**
         * The function returned successfully.
         */
        OK,

        /**
         * One of the arguments to the function was NULL when it was not expected.
         */
        NULL,

        /**
         * The friend number did not designate a valid friend.
         */
        FRIEND_NOT_FOUND,

        /**
         * This client is currently not connected to the friend.
         */
        FRIEND_NOT_CONNECTED,

        /**
         * The first byte of data was not in the specified range for the packet type.
         * This range is 200-254 for lossy, and 160-191 for lossless packets.
         */
        INVALID,

        /**
         * Attempted to send an empty packet.
         */
        EMPTY,

        /**
         * Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.
         */
        TOO_LONG,

        /**
         * Packet queue is full.
         */
        SENDQ
    }

    /**
    * This struct contains all the startup options for Tox. You can either allocate
    * this object yourself, and pass it to tox_options_default, or call
    * tox_options_new to get a new default options object.
    */
    [CCode (cname="struct Tox_Options", destroy_function="", has_type_id=false)]
    [Compact]
    public class Options {
        /**
        * The type of socket to create.
        *
        * If this is set to false, an IPv4 socket is created, which subsequently
        * only allows IPv4 communication.
        * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
        * IPv6 communication.
        */
        public bool ipv6_enabled;

        /**
        * Enable the use of UDP communication when available.
        *
        * Setting this to false will force Tox to use TCP only. Communications will
        * need to be relayed through a TCP relay node, potentially slowing them down.
        * Disabling UDP support is necessary when using anonymous proxies or Tor.
        */
        public bool udp_enabled;

        /**
        * Pass communications through a proxy.
        */
        public ProxyType proxy_type;

        /**
        * The IP address or DNS name of the proxy to be used.
        *
        * If used, this must be non-NULL and be a valid DNS name. The name must not
        * exceed 255 characters, and be in a NUL-terminated C string format
        * (255 chars + 1 NUL byte).
        *
        * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE.
        */
        public string? proxy_host;

        /**
        * The port to use to connect to the proxy server.
        *
        * Ports must be in the range (1, 65535). The value is ignored if
        * proxy_type is TOX_PROXY_TYPE_NONE.
        */
        public uint16 proxy_port;

        /**
        * The start port of the inclusive port range to attempt to use.
        *
        * If both start_port and end_port are 0, the default port range will be
        * used: [33445, 33545].
        *
        * If either start_port or end_port is 0 while the other is non-zero, the
        * non-zero port will be the only port in the range.
        *
        * Having start_port > end_port will yield the same behavior as if start_port
        * and end_port were swapped.
        */
        public uint16 start_port;

        /**
        * The end port of the inclusive port range to attempt to use.
        */
        public uint16 end_port;

        /**
        * The port to use for the TCP server (relay). If 0, the TCP server is
        * disabled.
        *
        * Enabling it is not required for Tox to function properly.
        *
        * When enabled, your Tox instance can act as a TCP relay for other Tox
        * instance. This leads to increased traffic, thus when writing a client
        * it is recommended to enable TCP server only if the user has an option
        * to disable it.
        */
        public uint16 tcp_port;

        /**
        * The type of savedata to load from.
        */
        public SaveDataType savedata_type;

        /**
        * The savedata.
        */
        [CCode (array_length_cname="savedata_length", array_length_type="size_t")]
        public uint8[] savedata_data;

        /**
         * Allocates a new Tox_Options object and initialises it with the default
         * options. This function can be used to preserve long term ABI compatibility by
         * giving the responsibility of allocation and deallocation to the Tox library.
         *
         * Objects returned from this function must be freed using the tox_options_free
         * function.
         *
         * @return A new Tox_Options object with default options or NULL on failure.
         */
        public Options (out ERR_OPTIONS_NEW err);

        /**
         * Initialises a Tox_Options object with the default options.
         *
         * The result of this function is independent of the original options. All
         * values will be overwritten, no values will be read (so it is permissible
         * to pass an uninitialised object).
         *
         * If options is NULL, this function has no effect.
         *
         * @param options An options object to be filled with default options.
         */
        public void default ();
    }

    /**
     * The Tox instance type. All the state associated with a connection is held
     * within the instance. Multiple instances can exist and operate concurrently.
     * The maximum number of Tox instances that can exist on a single network
     * device is limited. Note that this is not just a per-process limit, since the
     * limiting factor is the number of usable ports on a device.
     */
    [CCode (cname="Tox", free_function="tox_kill", cprefix="tox_", has_type_id=false)]
    [Compact]
    public class Tox {
        /**
         * Creates and initialises a new Tox instance with the options passed.
         *
         * This function will bring the instance into a valid state. Running the event
         * loop with a new instance will operate correctly.
         *
         * If loading failed or succeeded only partially, the new or partially loaded
         * instance is returned and an error code is set.
         *
         * @param options An options object as described above. If this parameter is
         *   NULL, the default options are used.
         *
         * @see iterate
         *
         * @return A new Tox instance pointer on success or NULL on failure.
         */
        public Tox (Options? options = null, out ERR_NEW? error = null);

        /**
         * Releases all resources associated with the Tox instance and disconnects from
         * the network.
         *
         * After calling this function, the Tox pointer becomes invalid. No other
         * functions can be called, and the pointer value can no longer be read.
         */
        public void kill ();

        /**
         * @param friend_number The friend number of the friend whose name changed.
         * @param name A byte array containing the same data as
         *   tox_friend_get_name would write to its `name` parameter.
         * @param length A value equal to the return value of
         *   tox_friend_get_name_size.
         */
        [CCode (cname="tox_friend_name_cb", has_target=true, has_type_id=false)]
        public delegate void FriendNameFunc (Tox self, uint32 friend_number, uint8[] name);

        /**
         * Set the callback for the `friend_name` event. Pass NULL to unset.
         *
         * This event is triggered when a friend changes their name.
         */
        public void callback_friend_name (FriendNameFunc callback);

        /**
         * @param friend_number The friend number of the friend whose status message
         *   changed.
         * @param message A byte array containing the same data as
         *   tox_friend_get_status_message would write to its `status_message` parameter.
         * @param length A value equal to the return value of
         *   tox_friend_get_status_message_size.
         */
        [CCode (cname="tox_friend_status_message_cb", has_target=true, has_type_id=false)]
        public delegate void FriendStatusMessageFunc (Tox self, uint32 friend_number, uint8[] message);

        /**
         * Set the callback for the `friend_status_message` event. Pass NULL to unset.
         *
         * This event is triggered when a friend changes their status message.
         */
        public void callback_friend_status_message (FriendStatusMessageFunc callback);

        /**
         * @param friend_number The friend number of the friend whose user status
         *   changed.
         * @param status The new user status.
         */
        [CCode (cname="tox_friend_status_cb", has_target=true, has_type_id=false)]
        public delegate void FriendStatusFunc (Tox self, uint32 friend_number, UserStatus status);

        /**
         * Set the callback for the `friend_status` event. Pass NULL to unset.
         *
         * This event is triggered when a friend changes their user status.
         */
        public void callback_friend_status (FriendStatusFunc callback);

        /**
         * @param friend_number The friend number of the friend whose connection status
         *   changed.
         * @param connection_status The result of calling
         *   tox_friend_get_connection_status on the passed friend_number.
         */
        [CCode (cname="tox_friend_connection_status_cb", has_target=true, has_type_id=false)]
        public delegate void FriendConnectionStatusFunc (Tox self, uint32 friend_number, ConnectionStatus connection_status);

        /**
         * Set the callback for the `friend_connection_status` event. Pass NULL to unset.
         *
         * This event is triggered when a friend goes offline after having been online,
         * or when a friend goes online.
         *
         * This callback is not called when adding friends. It is assumed that when
         * adding friends, their connection status is initially offline.
         */
        public void callback_friend_connection_status (FriendConnectionStatusFunc callback);

        /**
         * @param friend_number The friend number of the friend who started or stopped
         *   typing.
         * @param is_typing The result of calling tox_friend_get_typing on the passed
         *   friend_number.
         */
        [CCode (cname = "tox_friend_typing_cb", has_target=true, has_type_id=false)]
        public delegate void FriendTypingFunc (Tox self, uint32 friend_number, bool is_typing);

        /**
         * Set the callback for the `friend_typing` event. Pass NULL to unset.
         *
         * This event is triggered when a friend starts or stops typing.
         */
        public void callback_friend_typing (FriendTypingFunc callback);

        /**
         * @param friend_number The friend number of the friend who received the message.
         * @param message_id The message ID as returned from tox_friend_send_message
         *   corresponding to the message sent.
         */
        [CCode (cname = "tox_friend_read_receipt_cb", has_target=true, has_type_id=false)]
        public delegate void ReadReceiptFunc(Tox self, uint32 friend_number, uint32 message_id);

        /**
         * Set the callback for the `friend_read_receipt` event. Pass NULL to unset.
         *
         * This event is triggered when the friend receives the message sent with
         * tox_friend_send_message with the corresponding message ID.
         */
        public void callback_friend_read_receipt (ReadReceiptFunc callback);

        /**
         * @param public_key The Public Key of the user who sent the friend request.
         * @param message The message they sent along with the request.
         * @param length The size of the message byte array.
         */
        [CCode (cname="tox_friend_request_cb", has_target=true, has_type_id=false)]
        public delegate void FriendRequestFunc (Tox self, [CCode (array_length=false)] uint8[] public_key, [CCode (array_length_type="size_t")] uint8[] message);

        /**
         * Set the callback for the `friend_request` event. Pass NULL to unset.
         *
         * This event is triggered when a friend request is received.
         */
        public void callback_friend_request (FriendRequestFunc callback);

        /**
         * @param friend_number The friend number of the friend who sent the message.
         * @param message The message data they sent.
         * @param length The size of the message byte array.
         */
        [CCode (cname="tox_friend_message_cb", has_target=true, has_type_id=false)]
        public delegate void FriendMessageFunc (Tox self, uint32 friend_number, MessageType type, [CCode (array_length_type="size_t")] uint8[] message);

        /**
         * Set the callback for the `friend_message` event. Pass NULL to unset.
         *
         * This event is triggered when a message from a friend is received.
         */
        public void callback_friend_message (FriendMessageFunc callback);

        /**
         * When receiving TOX_FILE_CONTROL_CANCEL, the client should release the
         * resources associated with the file number and consider the transfer failed.
         *
         * @param friend_number The friend number of the friend who is sending the file.
         * @param file_number The friend-specific file number the data received is
         *   associated with.
         * @param control The file control command received.
         */
        [CCode (cname = "tox_file_recv_control_cb", has_target=true, has_type_id=false)]
        public delegate void FileControlReceiveFunc (Tox self, uint32 friend_number, uint32 file_number, FileControl control);

        /**
         * Set the callback for the `file_recv_control` event. Pass NULL to unset.
         *
         * This event is triggered when a file control command is received from a
         * friend.
         */
        public void callback_file_recv_control (FileControlReceiveFunc callback);

        /**
         * If the length parameter is 0, the file transfer is finished, and the client's
         * resources associated with the file number should be released. After a call
         * with zero length, the file number can be reused for future file transfers.
         *
         * If the requested position is not equal to the client's idea of the current
         * file or stream position, it will need to seek. In case of read-once streams,
         * the client should keep the last read chunk so that a seek back can be
         * supported. A seek-back only ever needs to read from the last requested chunk.
         * This happens when a chunk was requested, but the send failed. A seek-back
         * request can occur an arbitrary number of times for any given chunk.
         *
         * In response to receiving this callback, the client should call the function
         * `tox_file_send_chunk` with the requested chunk. If the number of bytes sent
         * through that function is zero, the file transfer is assumed complete. A
         * client must send the full length of data requested with this callback.
         *
         * @param friend_number The friend number of the receiving friend for this file.
         * @param file_number The file transfer identifier returned by tox_file_send.
         * @param position The file or stream position from which to continue reading.
         * @param length The number of bytes requested for the current chunk.
         */
        [CCode (cname = "tox_file_chunk_request_cb", has_target=true, has_type_id=false)]
        public delegate void FileChunkRequestFunc (Tox self, uint32 friend_number, uint32 file_number, uint64 position, size_t length);

        /**
         * Set the callback for the `file_chunk_request` event. Pass NULL to unset.
         *
         * This event is triggered when Core is ready to send more file data.
         */
        public void callback_file_chunk_request (FileChunkRequestFunc callback);

        /**
         * The client should acquire resources to be associated with the file transfer.
         * Incoming file transfers start in the PAUSED state. After this callback
         * returns, a transfer can be rejected by sending a TOX_FILE_CONTROL_CANCEL
         * control command before any other control commands. It can be accepted by
         * sending TOX_FILE_CONTROL_RESUME.
         *
         * @param friend_number The friend number of the friend who is sending the file
         *   transfer request.
         * @param file_number The friend-specific file number the data received is
         *   associated with.
         * @param kind The meaning of the file to be sent.
         * @param file_size Size in bytes of the file the client wants to send,
         *   UINT64_MAX if unknown or streaming.
         * @param filename Name of the file. Does not need to be the actual name. This
         *   name will be sent along with the file send request.
         * @param filename_length Size in bytes of the filename.
         */
        [CCode (cname = "tox_file_recv_cb", has_target=true, has_type_id=false)]
        public delegate void FileRecvFunc (Tox self, uint32 friend_number, uint32 file_number, FileKind kind, uint64 file_size, [CCode (array_length_type="size_t")] uint8[] filename);

        /**
         * Set the callback for the `file_recv` event. Pass NULL to unset.
         *
         * This event is triggered when a file transfer request is received.
         */
        public void callback_file_recv (FileRecvFunc callback);

        /**
         * When length is 0, the transfer is finished and the client should release the
         * resources it acquired for the transfer. After a call with length = 0, the
         * file number can be reused for new file transfers.
         *
         * If position is equal to file_size (received in the file_receive callback)
         * when the transfer finishes, the file was received completely. Otherwise, if
         * file_size was UINT64_MAX, streaming ended successfully when length is 0.
         *
         * @param friend_number The friend number of the friend who is sending the file.
         * @param file_number The friend-specific file number the data received is
         *   associated with.
         * @param position The file position of the first byte in data.
         * @param data A byte array containing the received chunk.
         * @param length The length of the received chunk.
         */
        [CCode (cname = "tox_file_recv_chunk_cb", has_target=true, has_type_id=false)]
        public delegate void FileRecvChunkFunc (Tox self, uint32 friend_number, uint32 file_number, uint64 position, uint8[] data);

        /**
         * Set the callback for the `file_recv_chunk` event. Pass NULL to unset.
         *
         * This event is first triggered when a file transfer request is received, and
         * subsequently when a chunk of file data for an accepted request was received.
         */
        public void callback_file_recv_chunk (FileRecvChunkFunc callback);

        /**
         * @param connection_status Whether we are connected to the DHT.
         */
        [CCode (cname="tox_self_connection_status_cb", has_target=true, has_type_id=false)]
        public delegate void ConnectionStatusFunc (Tox self, ConnectionStatus connection_status);

        /**
         * Set the callback for the `self_connection_status` event. Pass NULL to unset.
         *
         * This event is triggered whenever there is a change in the DHT connection
         * state. When disconnected, a client may choose to call tox_bootstrap again, to
         * reconnect to the DHT. Note that this state may frequently change for short
         * amounts of time. Clients should therefore not immediately bootstrap on
         * receiving a disconnect.
         *
         * TODO: how long should a client wait before bootstrapping again?
         */
        public void callback_self_connection_status (ConnectionStatusFunc callback);

        /**
         * Return whether we are connected to the DHT. The return value is equal to the
         * last value received through the `self_connection_status` callback.
         */
        public ConnectionStatus self_get_connection_status ();

        /**
         * Writes the Tox friend address of the client to a byte array. The address is
         * not in human-readable format. If a client wants to display the address,
         * formatting is required.
         *
         * @param address A memory region of at least TOX_ADDRESS_SIZE bytes. If this
         *   parameter is NULL, this function has no effect.
         * @see ADDRESS_SIZE
         */
        public void self_get_address ([CCode (array_length=false)] uint8[] address);

        /**
         * Copy the Tox Public Key (long term) from the Tox object.
         *
         * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
         *   this parameter is NULL, this function has no effect.
         */
        public void self_get_public_key ([CCode (array_length=false)] uint8[] public_key);

        /**
         * Copy the Tox Secret Key from the Tox object.
         *
         * @param secret_key A memory region of at least TOX_SECRET_KEY_SIZE bytes. If
         *   this parameter is NULL, this function has no effect.
         */
        public void self_get_secret_key ([CCode (array_length=false)] uint8[] secret_key);

        /**
         * Set the nickname for the Tox client.
         *
         * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is 0, the name
         * parameter is ignored (it can be NULL), and the nickname is set back to empty.
         *
         * @param name A byte array containing the new nickname.
         * @param length The size of the name byte array.
         *
         * @return true on success.
         */
        public bool self_set_name (uint8[] name, out ERR_SET_INFO error);

        /**
         * Return the length of the current nickname as passed to tox_self_set_name.
         *
         * If no nickname was set before calling this function, the name is empty,
         * and this function returns 0.
         *
         * see threading for concurrency implications.
         */
        public size_t self_get_name_size ();

        /**
         * Write the nickname set by tox_self_set_name to a byte array.
         *
         * If no nickname was set before calling this function, the name is empty,
         * and this function has no effect.
         *
         * Call tox_self_get_name_size to find out how much memory to allocate for
         * the result.
         *
         * @param name A valid memory location large enough to hold the nickname.
         *   If this parameter is NULL, the function has no effect.
         */
        public void self_get_name ([CCode (array_length = false)] uint8[] name);

        /**
         * Set the client's typing status for a friend.
         *
         * The client is responsible for turning it on or off.
         *
         * @param friend_number The friend to which the client is typing a message.
         * @param typing The typing status. True means the client is typing.
         *
         * @return true on success.
         */
        public bool self_set_typing (uint32 friend_number, bool typing, out ERR_FRIEND_DELETE error);

        /**
         * Return the number of friends on the friend list.
         *
         * This function can be used to determine how much memory to allocate for
         * tox_self_get_friend_list.
         */
        public size_t self_get_friend_list_size ();

        /**
         * Copy a list of valid friend numbers into an array.
         *
         * Call tox_self_get_friend_list_size to determine the number of elements to allocate.
         *
         * @param list A memory region with enough space to hold the friend list. If
         *   this parameter is NULL, this function has no effect.
         */
        public void self_get_friend_list ([CCode (array_length = false)] uint32[] list);

        public UserStatus status {
            [CCode (cname="tox_self_get_status")] get;
            [CCode (cname="tox_self_set_status")] set;
        }

        /**
         * Set the client's status message.
         *
         * Status message length cannot exceed TOX_MAX_STATUS_MESSAGE_LENGTH. If
         * length is 0, the status parameter is ignored (it can be NULL), and the
         * user status is set back to empty.
         */
        public bool self_set_status_message (uint8[] status_message, out ERR_SET_INFO error);

        /**
         * Return the length of the current status message as passed to tox_self_set_status_message.
         *
         * If no status message was set before calling this function, the status
         * is empty, and this function returns 0.
         *
         * see threading for concurrency implications.
         */
        public size_t self_get_status_message_size ();

        /**
         * Write the status message set by tox_self_set_status_message to a byte array.
         *
         * If no status message was set before calling this function, the status is
         * empty, and this function has no effect.
         *
         * Call tox_self_get_status_message_size to find out how much memory to allocate for
         * the result.
         *
         * @param status A valid memory location large enough to hold the status message.
         *   If this parameter is NULL, the function has no effect.
         */
        public void self_get_status_message ([CCode (array_length=false)] uint8[] status);

        public uint32 nospam {
            [CCode (cname="tox_self_get_nospam")] get;
            [CCode (cname="tox_self_set_nospam")] set;
        }

        /**
         * Writes the temporary DHT public key of this instance to a byte array.
         *
         * This can be used in combination with an externally accessible IP address and
         * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap node.
         *
         * Be aware that every time a new instance is created, the DHT public key
         * changes, meaning this cannot be used to run a permanent bootstrap node.
         *
         * @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this
         *   parameter is NULL, this function has no effect.
         */
        public void self_get_dht_id ([CCode (array_length=false)] uint8[] dht_id);

        /**
         * Return the UDP port this Tox instance is bound to.
         */
        public uint16 self_get_udp_port (out ERR_GET_PORT error);

        /**
         * Return the TCP port this Tox instance is bound to. This is only relevant if
         * the instance is acting as a TCP relay.
         */
        public uint16 self_get_tcp_port (out ERR_GET_PORT error);

        /**
         * Add a friend to the friend list and send a friend request.
         *
         * A friend request message must be at least 1 byte long and at most
         * TOX_MAX_FRIEND_REQUEST_LENGTH.
         *
         * Friend numbers are unique identifiers used in all functions that operate on
         * friends. Once added, a friend number is stable for the lifetime of the Tox
         * object. After saving the state and reloading it, the friend numbers may not
         * be the same as before. Deleting a friend creates a gap in the friend number
         * set, which is filled by the next adding of a friend. Any pattern in friend
         * numbers should not be relied on.
         *
         * If more than INT32_MAX friends are added, this function causes undefined
         * behaviour.
         *
         * @param address The address of the friend (returned by tox_self_get_address of
         *   the friend you wish to add) it must be TOX_ADDRESS_SIZE bytes.
         * @param message The message that will be sent along with the friend request.
         * @param length The length of the data byte array.
         *
         * @return the friend number on success, UINT32_MAX on failure.
         */
        public uint32 friend_add ([CCode (array_length=false)] uint8[] address, uint8[] message, out ERR_FRIEND_ADD error);

        /**
         * Add a friend without sending a friend request.
         *
         * This function is used to add a friend in response to a friend request. If the
         * client receives a friend request, it can be reasonably sure that the other
         * client added this client as a friend, eliminating the need for a friend
         * request.
         *
         * This function is also useful in a situation where both instances are
         * controlled by the same entity, so that this entity can perform the mutual
         * friend adding. In this case, there is no need for a friend request, either.
         *
         * @param public_key A byte array of length TOX_PUBLIC_KEY_SIZE containing the
         *   Public Key (not the Address) of the friend to add.
         *
         * @return the friend number on success, UINT32_MAX on failure.
         * see {@link friend_add} for a more detailed description of friend numbers.
         */
        public uint32 friend_add_norequest ([CCode (array_length=false)] uint8[] public_key, out ERR_FRIEND_ADD error);

        /**
         * Remove a friend from the friend list.
         *
         * This does not notify the friend of their deletion. After calling this
         * function, this client will appear offline to the friend and no communication
         * can occur between the two.
         *
         * @param friend_number Friend number for the friend to be deleted.
         *
         * @return true on success.
         */
        public bool friend_delete (uint32 friend_number, out ERR_FRIEND_DELETE error);

        /**
         * Return the friend number associated with that Public Key.
         *
         * @return the friend number on success, UINT32_MAX on failure.
         * @param public_key A byte array containing the Public Key.
         */
        public uint32 friend_by_public_key ([CCode (array_length=false)] uint8[] public_key, out ERR_FRIEND_BY_PUBLIC_KEY error);

        /**
         * Checks if a friend with the given friend number exists and returns true if
         * it does.
         */
        public bool friend_exists (uint32 friend_number);

        /**
         * Copies the Public Key associated with a given friend number to a byte array.
         *
         * @param friend_number The friend number you want the Public Key of.
         * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
         *   this parameter is NULL, this function has no effect.
         *
         * @return true on success.
         */
        public bool friend_get_public_key (uint32 friend_number, [CCode (array_length=false)] uint8[] public_key, out ERR_FRIEND_GET_PUBLIC_KEY error);

        /**
         * Return a unix-time timestamp of the last time the friend associated with a given
         * friend number was seen online. This function will return UINT64_MAX on error.
         *
         * @param friend_number The friend number you want to query.
         */
        public uint64 friend_get_last_online (uint32 friend_number, out ERR_FRIEND_GET_LAST_ONLINE error);

        /**
         * Return the length of the friend's name. If the friend number is invalid, the
         * return value is unspecified.
         *
         * The return value is equal to the `length` argument received by the last
         * `friend_name` callback.
         */
        public size_t friend_get_name_size (uint32 friend_number, out ERR_FRIEND_QUERY error);

        /**
         * Write the name of the friend designated by the given friend number to a byte
         * array.
         *
         * Call tox_friend_get_name_size to determine the allocation size for the `name`
         * parameter.
         *
         * The data written to `name` is equal to the data received by the last
         * `friend_name` callback.
         *
         * @param name A valid memory region large enough to store the friend's name.
         *
         * @return true on success.
         */
        public bool friend_get_name (uint32 friend_number, [CCode (array_length=false)] uint8[] name, out ERR_FRIEND_QUERY error);

        /**
         * Return the length of the friend's status message. If the friend number is
         * invalid, the return value is SIZE_MAX.
         */
        public size_t friend_get_status_message_size (uint32 friend_number, out ERR_FRIEND_QUERY error);

        /**
         * Write the status message of the friend designated by the given friend number to a byte
         * array.
         *
         * Call tox_friend_get_status_message_size to determine the allocation size for the `status_name`
         * parameter.
         *
         * The data written to `status_message` is equal to the data received by the last
         * `friend_status_message` callback.
         *
         * @param status_message A valid memory region large enough to store the friend's status message.
         */
        public bool friend_get_status_message (uint32 friend_number, [CCode (array_length=false)] uint8[] status_message, out ERR_FRIEND_QUERY error);

        /**
         * Return the friend's user status (away/busy/...). If the friend number is
         * invalid, the return value is unspecified.
         *
         * The status returned is equal to the last status received through the
         * `friend_status` callback.
         */
        public UserStatus friend_get_status (uint32 friend_number, out ERR_FRIEND_QUERY error);

        /**
         * Check whether a friend is currently connected to this client.
         *
         * The result of this function is equal to the last value received by the
         * `friend_connection_status` callback.
         *
         * @param friend_number The friend number for which to query the connection
         *   status.
         *
         * @return the friend's connection status as it was received through the
         *   `friend_connection_status` event.
         */
        public ConnectionStatus friend_get_connection_status (uint32 friend_number, out ERR_FRIEND_QUERY error);

        /**
         * Check whether a friend is currently typing a message.
         *
         * @param friend_number The friend number for which to query the typing status.
         *
         * @return true if the friend is typing.
         * @return false if the friend is not typing, or the friend number was
         *   invalid. Inspect the error code to determine which case it is.
         */
        public bool friend_get_typing (uint32 friend_number, out ERR_FRIEND_QUERY error);

        /**
         * Send a text chat message to an online friend.
         *
         * This function creates a chat message packet and pushes it into the send
         * queue.
         *
         * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
         * must be split by the client and sent as separate messages. Other clients can
         * then reassemble the fragments. Messages may not be empty.
         *
         * The return value of this function is the message ID. If a read receipt is
         * received, the triggered `friend_read_receipt` event will be passed this message ID.
         *
         * Message IDs are unique per friend. The first message ID is 0. Message IDs are
         * incremented by 1 each time a message is sent. If UINT32_MAX messages were
         * sent, the next message ID is 0.
         *
         * @param type Message type (normal, action, ...).
         * @param friend_number The friend number of the friend to send the message to.
         * @param message A non-NULL pointer to the first element of a byte array
         *   containing the message text.
         * @param length Length of the message to be sent.
         */
        public uint32 friend_send_message (uint32 friend_number, MessageType type, uint8[] message, out ERR_FRIEND_SEND_MESSAGE error);

        /**
         * Generates a cryptographic hash of the given data.
         *
         * This function may be used by clients for any purpose, but is provided
         * primarily for validating cached avatars. This use is highly recommended to
         * avoid unnecessary avatar updates.
         *
         * If hash is NULL or data is NULL while length is not 0 the function returns false,
         * otherwise it returns true.
         *
         * This function is a wrapper to internal message-digest functions.
         *
         * @param hash A valid memory location the hash data. It must be at least
         *   TOX_HASH_LENGTH bytes in size.
         * @param data Data to be hashed or NULL.
         * @param length Size of the data array or 0.
         *
         * @return true if hash was not NULL.
         */
        public static bool hash ([CCode (array_length=false)] uint8[] hash, uint8[] data);

        /**
         * Sends a file control command to a friend for a given file transfer.
         *
         * @param friend_number The friend number of the friend the file is being
         *   transferred to or received from.
         * @param file_number The friend-specific identifier for the file transfer.
         * @param control The control command to send.
         *
         * @return true on success.
         */
        public bool file_control (uint32 friend_number, uint32 file_number, FileControl control, out ERR_FILE_CONTROL error);

        /**
         * Sends a file seek control command to a friend for a given file transfer.
         *
         * This function can only be called to resume a file transfer right before
         * TOX_FILE_CONTROL_RESUME is sent.
         *
         * @param friend_number The friend number of the friend the file is being
         *   received from.
         * @param file_number The friend-specific identifier for the file transfer.
         * @param position The position that the file should be seeked to.
         */
        public bool file_seek (uint32 friend_number, uint32 file_number, int64 position, out ERR_FILE_SEEK error);

        /**
         * Copy the file id associated to the file transfer to a byte array.
         *
         * @param friend_number The friend number of the friend the file is being
         *   transferred to or received from.
         * @param file_number The friend-specific identifier for the file transfer.
         * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If
         *   this parameter is NULL, this function has no effect.
         *
         * @return true on success.
         */
        public bool file_get_file_id (uint32 friend_number, uint32 file_number, [CCode (array_length=false)] uint8[] file_id, out ERR_FILE_GET error);

        /**
         * Send a file transmission request.
         *
         * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename
         * should generally just be a file name, not a path with directory names.
         *
         * If a non-UINT64_MAX file size is provided, it can be used by both sides to
         * determine the sending progress. File size can be set to UINT64_MAX for streaming
         * data of unknown size.
         *
         * File transmission occurs in chunks, which are requested through the
         * `file_chunk_request` event.
         *
         * When a friend goes offline, all file transfers associated with the friend are
         * purged from core.
         *
         * If the file contents change during a transfer, the behaviour is unspecified
         * in general. What will actually happen depends on the mode in which the file
         * was modified and how the client determines the file size.
         *
         *  A. If the file size was increased
         *    a. and sending mode was streaming (file_size = UINT64_MAX), the behaviour
         *       will be as expected.
         *    a. and sending mode was file (file_size != UINT64_MAX), the
         *       file_chunk_request callback will receive length = 0 when Core thinks
         *       the file transfer has finished. If the client remembers the file size as
         *       it was when sending the request, it will terminate the transfer normally.
         *       If the client re-reads the size, it will think the friend cancelled the
         *       transfer.
         *  A. If the file size was decreased
         *    a. and sending mode was streaming, the behaviour is as expected.
         *    a. and sending mode was file, the callback will return 0 at the new
         *       (earlier) end-of-file, signalling to the friend that the transfer was
         *       cancelled.
         *  A. If the file contents were modified
         *    a. at a position before the current read, the two files (local and remote)
         *       will differ after the transfer terminates.
         *    a. at a position after the current read, the file transfer will succeed as
         *       expected.
         *    a. In either case, both sides will regard the transfer as complete and
         *       successful.
         *
         * @param friend_number The friend number of the friend the file send request
         *   should be sent to.
         * @param kind The meaning of the file to be sent.
         * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
         *   unknown or streaming.
         * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to
         *   uniquely identify file transfers across core restarts. If NULL, a random one will
         *   be generated by core. It can then be obtained by using tox_file_get_file_id().
         * @param filename Name of the file. Does not need to be the actual name. This
         *   name will be sent along with the file send request.
         * @param filename_length Size in bytes of the filename.
         *
         * @return A file number used as an identifier in subsequent callbacks. This
         *   number is per friend. File numbers are reused after a transfer terminates.
         *   On failure, this function returns UINT32_MAX. Any pattern in file numbers
         *   should not be relied on.
         */
        public uint32 file_send (uint32 friend_number, FileKind kind, uint64 file_size, [CCode (array_length=false)] uint8[]? file_id, uint8[]? filename, out ERR_FILE_SEND error);

        /**
         * Send a chunk of file data to a friend.
         *
         * This function is called in response to the `file_chunk_request` callback. The
         * length parameter should be equal to the one received though the callback.
         * If it is zero, the transfer is assumed complete. For files with known size,
         * Core will know that the transfer is complete after the last byte has been
         * received, so it is not necessary (though not harmful) to send a zero-length
         * chunk to terminate. For streams, core will know that the transfer is finished
         * if a chunk with length less than the length requested in the callback is sent.
         *
         * @param friend_number The friend number of the receiving friend for this file.
         * @param file_number The file transfer identifier returned by tox_file_send.
         * @param position The file or stream position from which to continue reading.
         * @return true on success.
         */
        public bool file_send_chunk (uint32 friend_number, uint32 file_number, uint64 position, uint8[] data, out ERR_FILE_SEND_CHUNK error);

        /**
         * Calculates the number of bytes required to store the tox instance with
         * tox_get_savedata. This function cannot fail. The result is always greater than 0.
         *
         * see threading for concurrency implications.
         */
        public uint32 get_savedata_size();

        /**
         * Store all information associated with the tox instance to a byte array.
         *
         * @param data A memory region large enough to store the tox instance data.
         *   Call tox_get_savedata_size to find the number of bytes required. If this parameter
         *   is NULL, this function has no effect.
         */
        public void get_savedata([CCode(array_length=false)] uint8[] data);

        /**
         * Sends a "get nodes" request to the given bootstrap node with IP, port, and
         * public key to setup connections.
         *
         * This function will attempt to connect to the node using UDP. You must use
         * this function even if Tox_Options.udp_enabled was set to false.
         *
         * @param address The hostname or IP address (IPv4 or IPv6) of the node.
         * @param port The port on the host on which the bootstrap Tox instance is
         *   listening.
         * @param public_key The long term public key of the bootstrap node
         *   (TOX_PUBLIC_KEY_SIZE bytes).
         * @return true on success.
         */
        public bool bootstrap (string address, uint16 port, [CCode (array_length=false)] uint8[] public_key, out ERR_BOOTSTRAP error);

        /**
         * Adds additional host:port pair as TCP relay.
         *
         * This function can be used to initiate TCP connections to different ports on
         * the same bootstrap node, or to add TCP relays without using them as
         * bootstrap nodes.
         *
         * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay.
         * @param port The port on the host on which the TCP relay is listening.
         * @param public_key The long term public key of the TCP relay
         *   (TOX_PUBLIC_KEY_SIZE bytes).
         * @return true on success.
         */
        public bool add_tcp_relay (string address, uint16 port, [CCode (array_length=false)] uint8[] public_key, out ERR_BOOTSTRAP error);

        /**
         * Return the time in milliseconds before tox_iterate() should be called again
         * for optimal performance.
         */
        public uint32 iteration_interval ();

        /**
         * The main loop that needs to be run in intervals of tox_iteration_interval()
         * milliseconds.
         */
        public void iterate ();

        /**
         * Send a custom lossy packet to a friend.
         *
         * The first byte of data must be in the range 200-254. Maximum length of a
         * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
         *
         * Lossy packets behave like UDP packets, meaning they might never reach the
         * other side or might arrive more than once (if someone is messing with the
         * connection) or might arrive in the wrong order.
         *
         * Unless latency is an issue, it is recommended that you use lossless custom
         * packets instead.
         *
         * @param friend_number The friend number of the friend this lossy packet
         *   should be sent to.
         * @param data A byte array containing the packet data.
         * @param length The length of the packet data byte array.
         *
         * @return true on success.
         */
        public bool friend_send_lossy_packet (uint32 friend_number, uint8[] data, out ERR_FRIEND_CUSTOM_PACKET? error);

        /**
         * Send a custom lossless packet to a friend.
         *
         * The first byte of data must be in the range 160-191. Maximum length of a
         * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
         *
         * Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
         * but with packets instead of a stream.
         *
         * @param friend_number The friend number of the friend this lossless packet
         *   should be sent to.
         * @param data A byte array containing the packet data.
         * @param length The length of the packet data byte array.
         *
         * @return true on success.
         */
        public bool friend_send_lossless_packet (uint32 friend_number, uint8[] data, out ERR_FRIEND_CUSTOM_PACKET? error);

        /**
         * @param friend_number The friend number of the friend who sent a lossy packet.
         * @param data A byte array containing the received packet data.
         * @param length The length of the packet data byte array.
         */
        [CCode (cname = "tox_file_recv_control_cb", has_target=true, has_type_id=false)]
        public delegate void FriendLossyPacketFunc (Tox self, uint32 friend_number, uint8[] data);

        /**
         * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset.
         */
        public void callback_friend_lossy_packet (FriendLossyPacketFunc callback);

        /**
         * @param friend_number The friend number of the friend who sent the packet.
         * @param data A byte array containing the received packet data.
         * @param length The length of the packet data byte array.
         */
        [CCode (cname = "tox_file_recv_control_cb", has_target=true, has_type_id=false)]
        public delegate void FriendLosslessPacketFunc (Tox self, uint32 friend_number, uint8[] data);

        /**
         * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset.
         */
        public void callback_friend_lossless_packet (FriendLosslessPacketFunc callback);

        /************************************
        **  Groupchats
        ************************************/

         /**
          * The callback for group invites
          *
          * data of length is what needs to be passed to join_groupchat().
          *
          * for what type means see ToxGroupChatType_
          */
        public delegate void GroupInviteFunc (Tox self, int32 friend_number, uint8 type, uint8[] data);

        /**
         * Set the callback for group invites.
         */
        public void callback_group_invite (GroupInviteFunc callback);

        public delegate void GroupMessageFunc (Tox self, int group_number, int peer_number, [CCode (array_length_type="uint16_t")] uint8[] message);

        /**
         * Set the callback for group messages.
         */
        public void callback_group_message (GroupMessageFunc callback);

        /**
         * The callback for group actions
         */
        public delegate void GroupActionFunc (Tox self, int group_number, int peer_number, [CCode (array_length_type="uint16_t")] uint8[] action);

        /**
         * Set the callback for group actions.
         */
        public void callback_group_action (GroupActionFunc callback);

        /**
         * The callback for title changes
         *
         * if peernumber == -1, then author is unknown (e.g. initial joining the group)
         */
        public delegate void GroupTitleFunc (Tox self, int group_number, int peer_number, uint8[] title);

        /**
         * Set callback function for title changes.
         */
        public void callback_group_title (GroupTitleFunc callback);

        /**
         * The callback for peer name list changes
         */
        public delegate void GroupNamelistChangeFunc (Tox self, int group_number, int peer_number, ToxCore.ChatChange change_type);

        /**
         * Set callback function for peer name list changes.
         *
         * It gets called every time the name list changes(new peer/name, deleted peer)
         */
        public void callback_group_namelist_change (GroupNamelistChangeFunc callback);

        /**
         * Creates a new groupchat and puts it in the chats array.
         *
         * @return group number on success, -1 on failure.
         */
        public int add_groupchat ();

        /**
         * Delete a groupchat from the chats array.
         *
         * @return 0 on success, -1 on failure.
         */
        public int del_groupchat (int group_number);

        /**
         * Copy the name of peernumber who is in groupnumber to name.
         * name must be at least TOX_MAX_NAME_LENGTH long.
         *
         * @return length of name on success, -1 on failure
         */
        public int group_peername (int group_number, int peer_number, [CCode (array_length=false)] uint8[] name);

        /**
         * Copy the public key of peernumber who is in groupnumber to public_key.
         * public_key must be TOX_PUBLIC_KEY_SIZE long.
         *
         * @return 0 on success, -1 on failure
         */
        public int group_peer_pubkey (int group_number, int peer_number, [CCode (array_length=false)] uint8[] public_key);

        /**
         * invite friendnumber to groupnumber
         * @return 0 on success, -1 on failure
         */
        public int invite_friend (int32 friend_number, int group_number);

        /**
         * Join a group (you need to have been invited first.) using data of length obtained
         * in the group invite callback.
         *
         * @return group number on success, -1 on failure.
         */
        public int join_groupchat (int32 friend_number, uint8[] data);

        /**
         * send a group message
         * @return 0 on success, -1 on failure
         */
        public int group_message_send (int group_number, uint8[] message);

        /**
         * send a group action
         * @return 0 on success, -1 on failure
         */
        public int group_action_send (int group_number, uint8[] action);

        /**
         * set the group's title, limited to MAX_NAME_LENGTH
         * @return 0 on success, -1 on failure
         */
        public int group_set_title (int group_number, uint8[] title);

        /**
         * Get group title from groupnumber and put it in title.
         * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
         *
         * @return length of copied title on success, -1 on failure.
         */
        public int group_get_title (int group_number, [CCode (array_length_type = "uint32_t")] ref uint8[] title);

        /**
         * Check if the current peernumber corresponds to ours.
         *
         * @return 1 if the peernumber corresponds to ours, 0 on failure.
         */
        public int group_peernumber_is_ours (int group_number, int peer_number);

        /**
         * @return the number of peers in the group chat on success, -1 on failure
         */
        public int group_number_peers (int group_number);

        /**
         * List all the peers in the group chat.
         *
         * Copies the names of the peers to the name[length][TOX_MAX_NAME_LENGTH] array.
         *
         * Copies the lengths of the names to lengths[length]
         *
         * returns the number of peers on success.
         *
         * @return -1 on failure.
         */
        /**
         *  TODO: Fix this. (tox_old.h:152)
         *  public int group_get_names (int group_number, uint8[])
         */

        /**
         * Return the number of chats in the instance m.
         * You should use this to determine how much memory to allocate
         * for copy_chatlist.
         */
        public uint32 count_chatlist ();

        /**
         * Copy a list of valid chat IDs into the array out_list.
         * If out_list is NULL, returns 0.
         * Otherwise, returns the number of elements copied.
         * If the array was too small, the contents
         * of out_list will be truncated to list_size.
         */
        public uint32 get_chatlist (out int32[] out_list);

        /**
         * return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
         *
         * @return -1 on failure, type on success.
         */
        public int group_get_type (int group_number);
    }
}
